<?php

class TWS {

        /** Argumentos dos registros de Web Services. */
        private static $regArgs = array();

        /** Argumentos para as chamadas do metodo addComplexType. */
        private static $complexTypeArgs = array();

        /** Nome do primeiro servico do tipo WebService configurado. */
        private static $firstRegService;


        /**
         * Registra um WebService.
         * Os parametros sao os mesmos fornecidos para o metodo 'register' do nusoap.
         */
        public static function registerWS($className, $methodName, $in, $out, $desc = "") {
            $args = func_get_args();

            // Registrando o webservice para o servico de nome fornecido.
            if (!isset(TWS::$firstRegService)) {
                TWS::$firstRegService = $className;
            }

            // Evita o registro de demais webservices para outras classes de servico.
            // Registra apenas o servico que contem o nome do servico fornecido na URL.
            if ($className == TWS::$firstRegService) {

                // Armazena os argumentos de registro para que posteriormente seja registrado.
                TWS::$regArgs[] = $args;
            }
        }

        /**
         * Adiciona um tipo complexo para geracao do WSDL. 
         * Os argumentos sao os mesmos utilizados pela api do NuSoap.
         */
        public static function addComplexTypeWS() {
            TWS::$complexTypeArgs[] = func_get_args();
        }

        /**
         * Inicia o servidor de webservice para os servicos registrados.
         * @param $service Nome da classe do servico.
         */
        public static function handleWS($service) {
            if (!class_exists(ucfirst($service))) {
                echo 'classe não existe';
                return;
            }

            // Forcando a instancia do servico.
            new $service;

            // Utiliza o nusoap apenas para criar o wsdl automaticamente.
            if (isset($_GET["wsdl"])) {
                include_once('framework/helpers/nusoap/nusoap.php');

                $soapServer = new soap_server();

                $soapServer->configureWSDL($service, "http://" . $_SERVER['HTTP_HOST'] . "/", "http://" . $_SERVER['HTTP_HOST'] . "/tws/" . $service);

                // Registrando os webservices.
                foreach (TWS::$regArgs as $args) {
                    $soapServer->register(
                            $args[1], // method name
                            $args[2], // in
                            $args[3], // out
                            "http://" . $_SERVER['HTTP_HOST'] . "/", // namespace
                            "http://" . $_SERVER['HTTP_HOST'] . "/tws/" . $service, // soapaction
                            false, false, isset($args[4]) ? $args[4] : "" // descricao
                            );
                }


                // Registrando os tipos complexos.
                foreach (TWS::$complexTypeArgs as $args) {
                    //Chamada exemplo: $soapServer->wsdl->addComplexType(args)
                    call_user_func_array(array($soapServer->wsdl, "addComplexType"), $args);
                }

                // Iniciando o servidor de ws, utilizado apenas para gerar o wsdl.
                $soapServer->service('');
            } else {
                // Cria uma pasta onde serao armazenados os caches de wsdl.
                if (!file_exists("wsdl")) {
                    mkdir("wsdl");
                }

                $wsdlFilename = "./wsdl/" . $service . ".wsdl";

                //TODO melhorar esta implementacao!!!
                //if (!file_exists($wsdlFilename)) {
                $wsdl = file_get_contents("http://" . $_SERVER["HTTP_HOST"] . "/tws/" . $service . "?wsdl");

                file_put_contents($wsdlFilename, $wsdl);
                //}
                // Iniciando servidor de web service
                $soap = new SoapServer($wsdlFilename, array('uri' => "http://" . $_SERVER['HTTP_HOST'] . "/tws/" . $service));

                $soap->setClass($service);
                $soap->handle();
            }
        }

    }

?>
